package scarlett;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import scarlett.util.WebFile;



public abstract  class ScarlettRuntime implements IScarlettRuntime 
{
	
	public boolean _debug = false;
	
	public ScarlettRuntime()
	{
		//System.out.println("Mama Constructor!");
	}
	private void DebugWrite(String str)
	{
		System.out.println("DEBUG:	" + str);
	}
	
	
	
	public  void ScarlettMain(String[] args)
	    {
	        try {
	        	
	        	System.out.println("Scarlett v. 1.0.0.0");
	        	run(args);
	        }
	        catch (Exception ex) {
	            ex.printStackTrace();
	        }
	    }
	 
	@Override
	public void Show(Object o) {
		
		if (_debug) DebugWrite("METHOD: Show");
		if (o != null)
		System.out.println(o.toString());

	}

	@Override
	public  Pattern GetPattern(String regExpPattern)
	{
		if (_debug) DebugWrite("METHOD: GetPattern");
		if (!regExpPattern.startsWith("'"))
		{
			Pattern retPattern = null;

			if (regExpPattern.equals("email"))
			{
				
				retPattern = Pattern.compile("[\\w\\.-]+@([\\w\\-]+\\.)+[a-zA-Z]{2,4}");
			}
			else if (regExpPattern.equals("date"))
			{
				retPattern = Pattern.compile("(january\\s*|march\\s*|april\\s*|may\\s*|june\\s*|july\\s*|august\\s*|september\\s*|october\\s*|november\\s*|december\\s*)?[0-1]?[1-9]\\s*(-|\\/|,)?\\s*([1-9]|0[1-9]|[12][0-9]|3[01])\\s*(-|\\/|,)\\s*(18|19|20|21)\\d{2}",Pattern.CASE_INSENSITIVE);
				
			}
			else if (regExpPattern.equals("uri"))
			{
				retPattern = Pattern.compile( "\\b(https?|ftp|file)://[-A-Z0-9+&@#/%?=~_|!:,.;]*[-A-Z0-9+&@#/%=~_|]",Pattern.CASE_INSENSITIVE);        				
			}
			else if (regExpPattern.equals("number"))
			{
				retPattern = Pattern.compile( "\\d+");
			}
			else if (regExpPattern.equals("everything"))
			{
				retPattern = Pattern.compile( ".*");
			}
			else
			{
				System.out.println("Unknown regular expression.  This needs to be implemented! ->" + regExpPattern + "<-");
			}
			return retPattern; 
		}
		else
		{
			//TODO: Go or it SAM...
			return Pattern.compile(regExpPattern.substring(1, regExpPattern.length() -1 ));			
		}
			
	}
	
	@Override
	public  List<String> Fetch(String uriOrSourceString,Pattern regEx)
	{
		if (_debug) DebugWrite("METHOD: Fetch");
		List<String> retList = new ArrayList<String>();
		String sourceString = null;
		if (uriOrSourceString.toLowerCase().startsWith("http://") || uriOrSourceString.toLowerCase().startsWith("file://"))
		{
			sourceString = GetResourceAsString(uriOrSourceString);
		}
		else
		{
			sourceString = uriOrSourceString;
		}
		if (sourceString != null)
		{
			 Matcher m = regEx.matcher(sourceString);
		     while (m.find())
		    	 retList.add(m.group());

			
			//TODO: regexp first...
			
			return retList;
		}
		else
		{
			return retList;
		}
	}
	@Override
	public String GetResourceAsString(String uri) {
		String retVal = null;
		if (uri.toLowerCase().startsWith("http://"))
		{
			WebFile wf = new WebFile();
			try {
				Object val = wf.Fetch(uri);
				if (val == null  )
				{
					retVal = "Web file returned NULL";
				}
				else if( val instanceof String)
				{
					retVal = (String) val;
				}
				else if(val instanceof Byte[])
				{
					retVal = "Did not find a string, found an Byte Array of size " + ((Byte[]) val).length;
					
				}
				else
				{
					retVal = "Ignoring ->" + val.getClass().getName();	
				}
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				System.err.println("Malformed URI ->" + uri + "<-");
				//e.printStackTrace();
			} catch (SocketTimeoutException e) {
				System.err.println("ERROR: Could not connect to \"" + uri + "\". Check your internet connection and the URL.");
			} catch (IOException e) {
				System.err.println("ERROR: while retrieving uri ->" + uri + "<-");
				// TODO Auto-generated catch block
				//e.printStackTrace();
			}
			catch (Exception e) {
				System.err.println("Genearl ERROR: while retrieving uri ->" + uri + "<-");
				// TODO Auto-generated catch block
				//e.printStackTrace();
			}
			
		}
		else if(uri.toLowerCase().startsWith("file://")){
			
			try{
				uri = uri.replace("file://", "");
				BufferedReader bf = new BufferedReader(new FileReader(new File(uri)));
				StringBuilder sb = new StringBuilder();
				
				while (bf.ready()){
					sb.append(bf.readLine());
				}
				
				retVal = sb.toString();
			}catch (Exception e) {
				e.printStackTrace();
			}
			
		}
		else
		{
			return "NOT Implemented Yet";
		}
		return retVal;
	}
	
	/**
	 * Compares the two arguments and determines if they are equal.
	 * See ScarlettComparator.isSameAs(Object, Object)
	 * @param a
	 * @param b
	 * @return true if the two objects are equal
	 */
	public boolean IsSameAs(Object a, Object b) {
		return new ScarlettComparator().isSameAs(a, b);
	}
	
	/**
	 * Checks if the first argument is an instance of the second's type.
	 * See ScarlettComparator.isA(Object, Object)
	 * @param a
	 * @param b
	 * @return true if the first argument is an instance of the second's type.
	 */
	public boolean IsA(Object a, Pattern b) {
		return new ScarlettComparator().isA(a, b);
	}
	
	/**
	 * Checks if the first argument contains an instance of second argument.
	 * See ScarlettComparator.contains(Object, Object)
	 * @param a
	 * @param b
	 * @return true if the first argument contains an instance of second argument.
	 */
	public boolean Contains(Object a, Object b) {
		return new ScarlettComparator().contains(a, b);
	}
	
	/**
	 * Checks if the first argument is larger than the second argument.
	 * See ScarlettComparator.isLargerThan(Object, Object)
	 * @param a
	 * @param b
	 * @return true if the first argument is larger than the second argument.
	 */
	public boolean IsLargerThan(Object a, Object b) {
		return new ScarlettComparator().isLargerThan(a, b);
	}
	
	/**
	 * Checks if the first argument is smaller than the second argument.
	 * See ScarlettComparator.isSmallerThan(Object, Object)
	 * @param a
	 * @param b
	 * @return true if the first argument is smaller than the second argument.
	 */
	public boolean IsSmallerThan(Object a, Object b) {
		return new ScarlettComparator().isSmallerThan(a, b);
	}
	
	/**
	 * Inserts one item into another.
	 * @param from
	 * @param to
	 */
	public void Insert(Object from, Object to) {
		new ScarlettSetOperator().Insert(from, to);
	}
	
	/**
	 * Removes one object from another.
	 * See the docs for this method in ScarlettSetOperator.
	 * @param object
	 * @param from
	 */
	public void Remove(Object object, Object from) {
		new ScarlettSetOperator().Remove(object, from);
	}
	
	/**
	 * Performs a set union on the first two collections and stores it into the destination.
	 * @param col1
	 * @param col2
	 * @param dest
	 */
	public void Join(Object col1, Object col2, Object dest) {
		new ScarlettSetOperator().Join(col1, col2, dest);
	}
	
	
	/**
	 * Appends input to given file 
	 * @param uri path to file
	 * @param input string to append to file
	 */
	public boolean appendToFile(Object uri, Object input){
		//System.out.println("append to file");
		//System.out.println("Uri : " + uri);
		//System.out.println("input : " + input);
		
		Object thisInput = null;
		
		if(uri !=null && input != null && uri instanceof String )//&& input instanceof String)
		{
			try {
				URI fileURI = new URI((String)uri);
				
				String stringUri = (String) uri;
				
				if(input instanceof Integer)
				{
					thisInput = ((Integer) input).toString();
				}					
				else if (input instanceof java.util.ArrayList)
				{
					
					StringBuilder sb = new StringBuilder();
					for (String eachString :(List<String>)input)
					{
						sb.append(eachString + "\n");
						
					}
					thisInput = sb.toString();
				}
				else
				{
					thisInput = (String) input;
				}
					
				
				//System.out.println("stringINput is : " + thisInput);
			
				if(stringUri.startsWith("file://")){
				
				
					try{
					    // Create file 
						File tempFile = new File (fileURI);
					    FileWriter fstream = new FileWriter(tempFile.getCanonicalPath(), true);
				        BufferedWriter out = new BufferedWriter(fstream);

				        out.append((String)thisInput);
				        
					    //Close the output stream
					    out.newLine();
					    out.close();
					    return true;
					    }catch (Exception e){//Catch exception if any
					      System.err.println("Error: " + e.getMessage());
					      return false;
				    }
				}
				else
				{
						return false;
				}
			} catch (URISyntaxException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
				return false;
			}

		}
		else{
			return false;
		}
		
		    
		
	}
	
	public abstract  void run(String[] args); 
	 
	/*
	public static void run(String[] args) {
		// TODO Auto-generated method stub
		
		System.out.println("Upper Guy.");	
	}
	 */
	
	public static final Pattern EMAIL_PATTERN = 
		Pattern.compile("^([0-9a-zA-Z]([-\\.\\w]*[0-9a-zA-Z])*@(([0-9a-zA-Z]) ([-\\w]*[0-9a-zA-Z])*\\.) [a-zA-Z]{2,9})$");
	public static final Pattern DATE_PATTERN =
		Pattern.compile("^[0-1][1-9][- / ]?(0[1-9]|[12][0-9]|3[01])[- /]?(18|19|20|21)\\d{2}$",Pattern.CASE_INSENSITIVE);
	public static final Pattern URI_PATTERN =
		Pattern.compile("\\b(https?|ftp|file)://[-A-Z0-9+&@#/%?=~_|!:,.;]*[-A-Z0-9+&@#/%=~_|]",Pattern.CASE_INSENSITIVE);
	public static final Pattern NUMBER_PATTERN = 
		Pattern.compile("\\d+");
	public static final Pattern EVERYTHING_PATTERN = 
		Pattern.compile(".*");
		
}
